package util;

import commom.ColorAndXY;
import commom.XY;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;

public class Util {

    public static void main(String[] args) throws AWTException, InterruptedException, IOException {
        DebuggerLine debuggerLine = new DebuggerLine();
        String pngNeedRobot = "img/need-robot-1920x1200.png";
        ColorAndXY[] colorAndXIES = readColorAndXYByFilePath(pngNeedRobot);
        printImg(colorAndXIES);
        Robot robot = new Robot();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();//获取屏幕大小
        Rectangle screenRectangle = new Rectangle(screenSize);//根据屏幕大小创建一个矩形
        while (true) {
            BufferedImage screenCapture = robot.createScreenCapture(screenRectangle);
            // ImageIO.write(screenCapture, "png", new File("C:\\Users\\Johnson\\Pictures\\截图debugger.png"));
            long startTime = System.currentTimeMillis();
            Vector<XY> imagePosition = findImagePosition(screenCapture, colorAndXIES);
            if (!imagePosition.isEmpty()) {
                System.out.println(imagePosition + " " + (System.currentTimeMillis() - startTime));
                XY xy = imagePosition.firstElement();
                debuggerLine.drawLine(xy.getX(), xy.getY());
            }
            Thread.sleep(10);
        }
    }

    /**
     * 　　　鷇鷇　　　　　　　　　鷇鷇
     * 　　　鷇鷇　　　　　　　　　鷇鷇
     * 　　　鷇鷇　　　　鷇鷇鷇鷇鷇鷇鷇鷇鷇鷇鷇鷇鷇
     *
     * @param colorAndXIES readColorAndXYByFilePath的返回值
     */
    public static void printImg(ColorAndXY[] colorAndXIES) {
        Optional<ColorAndXY> maxX = Arrays.stream(colorAndXIES).max(Comparator.comparingInt(a -> a.x));
        Optional<ColorAndXY> maxY = Arrays.stream(colorAndXIES).max(Comparator.comparingInt(a -> a.y));
        for (int y = 0; y <= maxY.get().y; y++) {
            StringBuilder sb = new StringBuilder();
            for (int x = 0; x <= maxX.get().x; x++) {
                Stream<ColorAndXY> stream = Arrays.stream(colorAndXIES);
                int finalX = x;
                int finalY = y;
                Optional<ColorAndXY> first = stream.filter(colorAndXY -> colorAndXY.x == finalX && colorAndXY.y == finalY).findFirst();
                if (first.isPresent())
                    sb.append("鷇");
                else
                    sb.append("　");
            }
//            String s = sb.toString().replaceAll("。+$", "");
            System.out.println(sb);
        }
    }

    /**
     * 读取图片信息 用于后续找图
     *
     * @param filePath 图片路径 new File(filePath)
     * @return
     */
    public static ColorAndXY[] readColorAndXYByFilePath(String filePath) {
        InputStream inputStream = getRealFile(filePath);
        return readColorAndXYByFilePath(inputStream);
    }

    /**
     * 读取图片信息 用于后续找图
     *
     * @param fileInputStream 图片路径 new File(filePath)
     * @return
     */
    public static ColorAndXY[] readColorAndXYByFilePath(InputStream fileInputStream) {
        try {
            BufferedImage bufferedImage = ImageIO.read(fileInputStream);
            int w = bufferedImage.getWidth();
            int h = bufferedImage.getHeight();
            ArrayList<ColorAndXY> res = new ArrayList<>();
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    int rgb = bufferedImage.getRGB(x, y);
                    // 不等于透明时，保存用于后续找图
                    if (rgb != 0) {
                        res.add(new ColorAndXY(x, y, rgb));
                    }
                }
            }
            return res.toArray(new ColorAndXY[0]);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 从屏幕截图中精确查找对应图片位置
     *
     * @param screenCapture 截图
     * @param arrColorAndXY 需要查找的图片位置颜色信息
     * @return XY 位置信息
     */
    public static Vector<XY> findImagePosition(BufferedImage screenCapture, ColorAndXY[] arrColorAndXY) {
        int w = screenCapture.getWidth();
        int h = screenCapture.getHeight();

        ExecutorService executorService = Executors.newFixedThreadPool(5);
        AtomicInteger index = new AtomicInteger(0);
        int max = w * h;
        Vector<XY> matchXYList = new Vector<>();
        Runnable runnable = () -> {
            while (true) {
                int i = index.getAndIncrement();
                if (i >= max)
                    break;
                int x = i % w;
                int y = i / w;
                boolean allMatch = true;
                for (ColorAndXY colorAndXY : arrColorAndXY) {
                    int checkX = x + colorAndXY.x;
                    int checkY = y + colorAndXY.y;
                    try {
                        int rgb = screenCapture.getRGB(checkX, checkY);
                        if (rgb != colorAndXY.rgb) {
                            allMatch = false;
                            break;
                        }
                    } catch (ArrayIndexOutOfBoundsException e) {
                        allMatch = false;
                        break;
                    }
                }
                if (allMatch)
                    matchXYList.add(new XY(x, y));
            }
        };
        for (int i = 0; i < 5; i++)
            executorService.submit(runnable);
        executorService.shutdown();
        while (!executorService.isTerminated()) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
        }
        return matchXYList;
    }

    /**
     * 从屏幕截图中相似查找对应图片位置
     *
     * @param screenCapture 截图
     * @param arrColorAndXY 需要查找的图片位置颜色信息
     * @param similar       相似度 1：完全相同 0.9：非常像 0.1：但凡有点像都可以
     * @return XY 位置信息
     */
    public static XY findTheLocationOfSimilarImages(BufferedImage screenCapture, ColorAndXY[] arrColorAndXY, double similar) {
        int w = screenCapture.getWidth();
        int h = screenCapture.getHeight();

        ExecutorService executorService = Executors.newFixedThreadPool(5);
        AtomicInteger index = new AtomicInteger(0);
        int max = w * h;
        AtomicReference<XY> returnXY = new AtomicReference<>();
        Runnable runnable = () -> {
            while (returnXY.get() == null) {
                int i = index.getAndIncrement();
                if (i >= max)
                    break;
                int x = i % w;
                int y = i / w;
                boolean allMatch = true;
                for (ColorAndXY colorAndXY : arrColorAndXY) {
                    int checkX = x + colorAndXY.x;
                    int checkY = y + colorAndXY.y;
                    try {
                        int rgb = screenCapture.getRGB(checkX, checkY);
                        // 判断颜色近似
                        int r = (rgb & 0xff0000) >> 16;
                        int g = (rgb & 0xff00) >> 8;
                        int b = (rgb & 0xff);

                        if (!isColorLike(r, colorAndXY.realRgb.getR(), similar) ||
                                !isColorLike(g, colorAndXY.realRgb.getG(), similar) ||
                                !isColorLike(b, colorAndXY.realRgb.getB(), similar)) {
                            allMatch = false;
                            break;
                        }
                    } catch (ArrayIndexOutOfBoundsException e) {
                        allMatch = false;
                        break;
                    }
                }
                if (allMatch)
                    returnXY.set(new XY(x, y));
            }
        };
        for (int i = 0; i < 5; i++)
            executorService.submit(runnable);
        executorService.shutdown();
        while (!executorService.isTerminated()) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
            }
        }
        return returnXY.get();
    }

    public static boolean isColorLike(int rgb1, int rgb2, double similar) {
        return Math.abs(rgb1 - rgb2) / 255.0 <= (1 - similar);
    }

    public static boolean isDev = false;

    public static InputStream getRealFile(String path) {
        if (isDev) {
            path = "img/" + path;
            try {
                File file = new File(path);
                return new FileInputStream(file);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        } else {
            System.out.println("当前路径：" + Util.class.getResource(""));
            URL resource = Util.class.getResource("/" + path);

            System.out.println("打开文件：" + "/" + path);
            try {
                InputStream inputStream = resource.openStream();
                return inputStream;
            } catch (IOException e) {
                System.out.println("文件找不到异常" + path);
                throw new RuntimeException(e);
            }
        }
    }
}
